import ora from "ora";
import chalk from "chalk";
import fs from "fs-extra";
import OpenAI from "openai";
import path from "node:path";

const openai = new OpenAI({
  apiKey: "sk-4728357168a33d442badd2fc37d62a4f01",
  baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
});

/**
 * 递归读取指定目录及其子目录中的文件，并筛选指定后缀的文件，返回文件名与内容的映射
 * @param {string} directory - 要读取的目录路径
 * @param {string[]} extensions - 要筛选的文件后缀数组（例如 [".txt", ".js"]）
 * @param {string[]} excludeFolders - 要排除的文件夹名称数组（例如 ["node_modules", "dist"]）
 * @returns {Promise<Object>} 返回一个包含文件名与内容的对象
 */
async function readFilesAndContentsRecursive(
  directory,
  extensions,
  excludeFolders = []
) {
  const excludeSet = new Set(
    excludeFolders.map((folder) => folder.toLowerCase())
  );
  const lowerCaseExtensions = extensions.map((ext) => ext.toLowerCase());

  async function readDirectory(dir) {
    try {
      const entries = await fs.readdir(dir, { withFileTypes: true });
      let result = {};

      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);

        if (entry.isDirectory()) {
          // 如果是目录，检查是否需要排除
          if (excludeSet.has(entry.name.toLowerCase())) {
            continue; // 跳过排除的文件夹
          }
          // 递归读取
          const nestedResult = await readDirectory(fullPath);
          result = { ...result, ...nestedResult };
        } else if (
          entry.isFile() &&
          lowerCaseExtensions.includes(path.extname(entry.name).toLowerCase())
        ) {
          // 如果是文件，且后缀匹配，则读取内容
          const content = await fs.readFile(fullPath, "utf-8");
          result[fullPath] = content; // 使用完整路径作为键
        }
      }

      return result;
    } catch (err) {
      throw new Error(`读取目录或文件失败: ${err.message}`);
    }
  }

  return readDirectory(directory);
}

async function getResponse(messages) {
  try {
    const response = await openai.chat.completions.create({
      // https://help.aliyun.com/zh/model-studio/getting-started/models
      model: "qwen-plus",
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        { role: "user", content: `下面的代码有什么优化建议？\n${messages}` },
      ],
    });
    return response.choices[0].message.content;
  } catch (error) {
    console.error("Error fetching response:", error);
    throw error; // 重新抛出异常以便上层处理
  }
}

function extractAlphanumericCharacters(str) {
  /**
   * 提取字符串中除数字和字母以外的其他字符
   * @param {string} str - 输入字符串
   * @returns {string[]} - 包含非数字和字母字符的数组
   */
  return str.split('').filter(char => /[a-zA-Z0-9]/.test(char)).join('');
}

async function main() {
  const spinner = ora("🏃 批改中...").start();
  const entry = "./zhangsan";
  const output = "result";
  const extension = [".ts", ".tsx", ".html", ".js", ".css"];
  const content = await readFilesAndContentsRecursive(entry, extension, [
    "node_modules",
  ]);

  let str = "";
  let idx = 0
  for (const attr in content) {
    idx++
    spinner.text = chalk.white(`批改中：${attr}`);
    const aiRes = await getResponse(content[attr]);
    spinner.succeed(chalk.green(`批改完成：${attr}`)).start();
    str += `# ${idx < 10 ? ('0'+idx) : idx}. ${attr}\n\n${aiRes}\n\n`;
  }

  const filePath = path.join(process.cwd(), output, `${extractAlphanumericCharacters(entry)}.md`);
  fs.outputFileSync(filePath, str, "utf8");
  spinner.succeed(chalk.bgGreen.bold(`批改完成，结果已保存至：${filePath}`));
  spinner.stop();
}

main();
